// +----------------------------------------------------------------------
//  UyghurCharUtils.swift
//  UyghurCharUtils
// +----------------------------------------------------------------------
//  Created by Erbash on 2022/11/3.
// +----------------------------------------------------------------------
//  Project Url: https://gitee.com/kerindax/UyghurCharUtils
// +----------------------------------------------------------------------
import Foundation
import JavaScriptCore

struct UyghurCharUtils {
    
    /// 转换类型枚举
    enum ConvertType: String {
        case Basic2Extend       // 基本区 转换 扩展
        case Extend2Basic       // 扩展区 转换 基本区
        case Basic2RExtend      // 基本区 转换 反向扩展区
        case RExtend2Basic      // 反向扩展区 转换 基本区
        
        case BasicSyllable      // 音节索引
    }
    
    private lazy var context: JSContext = {
        let js: JSContext = JSContext(virtualMachine: virtualMachine)
        return js
    }()
    
    private lazy var virtualMachine: JSVirtualMachine = {
        let js: JSVirtualMachine = JSVirtualMachine()
        return js
    }()
    
    static var Shared = UyghurCharUtils()
    
    
    private init() {
        guard let script = uyghurCharUtilsScript else {
            return
        }
        
        context.evaluateScript(script)
        context.evaluateScript(helperScript)
        context.exceptionHandler = {context, exception in
            guard let msg = exception?.toString() else {
                return
            }
            
            print("UyghurCharUtils ExceptionHandlerMassage: \(msg)")
        }
    }
}


// MARK: - PublicMethods

internal extension UyghurCharUtils {
    
    /// 便捷转换函数
    /// - Parameters:
    ///   - text: 原文本
    ///   - type: 转换类型
    /// - Returns: 转换结果
    mutating func Convert(_ text: String, type: ConvertType) -> String? {
        return invokeMethod(type, withArgument: text)
    }
    
    /// 基本区 转 音节索引
    /// - Parameter text: 基本区文本
    /// - Returns: 音节索引文本
    mutating func BasicSyllable(_ text: String) -> String?  {
        return invokeMethod(.BasicSyllable, withArgument: text)
    }

    /// 基本区 转换 扩展区
    /// - Parameter text: 基本区文本
    /// - Returns: 扩展区文本
    mutating func Basic2Extend(_ text: String) -> String? {
        return invokeMethod(.Basic2RExtend, withArgument: text)
    }
    
    /// 扩展区 转换 基本区
    /// - Parameter text: 扩展区文本
    /// - Returns: 基本区文本
    mutating func Extend2Basic(_ text: String) -> String? {
        return invokeMethod(.Extend2Basic, withArgument: text)
    }

    /// 基本区 转换 反向扩展区
    /// - Parameter text: 基本区文本
    /// - Returns: 反向扩展区文本
    mutating func Basic2RExtend(_ text: String) -> String? {
        return invokeMethod(.Basic2RExtend, withArgument: text)
    }
    
    /// 反向扩展区 转换 基本区
    /// - Parameter text: 反向扩展区文本
    /// - Returns: 基本区文本
    mutating func RExtend2Basic(_ text: String) -> String? {
        return invokeMethod(.RExtend2Basic, withArgument: text)
    }
}


// MARK: - PrivateMethods

private extension UyghurCharUtils {
    
    mutating func invokeMethod(_ method: ConvertType, withArgument text: String) -> String? {
        guard let result = invokeMethod(method.rawValue, withArgument: text)?.toString() else {
            return nil
        }
        return result
    }
    
    mutating func invokeMethod(_ method: String!, withArgument text: String) -> JSValue? {
        guard let method = self.context.objectForKeyedSubscript(method) else {
            return nil
        }

        guard !method.isUndefined else {
            return nil
        }
        
        guard let result = method.call(withArguments: [text]) else {
            return nil
        }
        
        return result
    }
}


// MARK: - PrivatePropertys

private extension UyghurCharUtils {
    
    var uyghurCharUtilsScript: String? {
        guard let url = Bundle.main.url(forResource: "UyghurCharUtils", withExtension: "js") else {
            print("UyghurCharUtils ErrorMassage: 无法获取 UyghurCharUtils.js 文件路径, 请确认是否已导入 UyghurCharUtils.js")
            return nil
        }
        
        do {
            let v = try String(contentsOf: url, encoding: .utf8)
            return v
        } catch {
            print("UyghurCharUtils ErrorMassage: 无法获取 UyghurCharUtils.js 源码\(error.localizedDescription)")
            return nil
        }
    }
    
    var helperScript : String {
        return """
var utils  = new UyghurCharUtils();

// 基本区 转换 扩展区
function Basic2Extend(t) {
    return utils.Basic2Extend(t)
}

// 扩展区 转换 基本区
function Extend2Basic(t) {
    return utils.Extend2Basic(t)
}

// 基本区 转换 反向扩展区
function Basic2RExtend(t) {
    return utils.Basic2RExtend(t)
}

// 反向扩展区 转换 基本区
function RExtend2Basic(t) {
    return utils.RExtend2Basic(t)
}

// 音节索引
function BasicSyllable(t) {
    return utils.BasicSyllable(t);
}
"""
    }
}
